using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.ServiceModel;
using System.Threading;
using AutoMapper;
using Core;
using IglooCoder.Commons.WcfNhibernate;
using Infrastucture;
using WcfService1.DTO;
using Omu.ValueInjecter;

namespace WcfService1
{
    // NOTE: You can use the "Rename" command on the "Refactor" MutasiWarehouse to change the class name "MutasiWarehouseServices" in code, svc and config file together.
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    [NHibernateContext]
    public class MutasiWarehouseServices : IMutasiWarehouseServices
    {
        private readonly MutasiWarehouseRepository MutasiWarehouseRepository;
        private readonly InventoryWarehouseRepository _iwRepository;
        private readonly WcfSessionStorage _session;
        private readonly MutasiStokRepository mutasiStokRepository;
        private InventoryRepository InventoryRep;
        private AppParamRepository paramRepository;

        public MutasiWarehouseServices()
        {
            Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
            _session = new WcfSessionStorage();
            MutasiWarehouseRepository = new MutasiWarehouseRepository(_session);
            InventoryRep = new InventoryRepository(_session);
            mutasiStokRepository = new MutasiStokRepository(_session);
            _iwRepository = new InventoryWarehouseRepository(_session);
            paramRepository = new AppParamRepository(_session);
        }

        #region IMutasiWarehouseServices Members

        public List<MutasiWarehouseDTO> GetList(int page, out long recordCount, string sortProperty = null,
                                                string sortType = "ASC")
        {
            var MutasiWarehouses = new List<MutasiWarehouse>();
            var Results = new List<MutasiWarehouseDTO>();

            if (string.IsNullOrEmpty(sortProperty))
            {
                MutasiWarehouses = MutasiWarehouseRepository.GetDataPaged(page, 30, "TglMutasi", "DESC").ToList();
            }
            else
            {
                MutasiWarehouses = MutasiWarehouseRepository.GetDataPaged(page, 30, sortProperty, sortType).ToList();
            }

            recordCount = MutasiWarehouseRepository.RecordCount;


            return (from m in MutasiWarehouses
                    select
                        new MutasiWarehouseDTO()
                            {
                                NoMutasi = m.NoMutasi,
                                TglMutasi = m.TglMutasi,
                                Description = m.Description,
                                FromWarehouse = new WarehouseDTO() {KodeWarehouse = m.FromWarehouse.KodeWarehouse},
                                ToWarehouse = new WarehouseDTO() {KodeWarehouse = m.ToWarehouse.KodeWarehouse}
                            }
                   ).ToList();
        }

        public bool Save(MutasiWarehouseDTO MutasiWarehouseDTO)
        {
            bool res;
            bool isNew = false;
            try
            {
                MutasiWarehouse MutasiWarehouse =
                    MutasiWarehouseRepository.GetDataOne(x => x.NoMutasi == MutasiWarehouseDTO.NoMutasi);
                var paramRounded = paramRepository.GetDataOne(x => x.AppParamName == "BatasRound");
                Decimal batasRounded = Decimal.Parse(paramRounded.AppParamValue);

                if (MutasiWarehouse == null)
                {
                    MutasiWarehouse = new MutasiWarehouse();
                    isNew = true;
                }
               

                MutasiWarehouseRepository.ExecuteTransactionNative(() =>
                                                                       {
                                                                           if (! isNew)
                                                                           {
                                                                               //hapus dulu mutasistokwarehousenya
                                                                               mutasiStokRepository.DeleteMutasiStok(MutasiWarehouse.NoMutasi);
                                                                               MutasiWarehouseRepository.Delete(MutasiWarehouse);

                                                                               var NewMutasiWarehouse = new MutasiWarehouse();
                                                                               NewMutasiWarehouse.modified_date = DateTime.Now;
                                                                               NewMutasiWarehouse.created_date = MutasiWarehouse.created_date;
                                                                               Mapper.Map(MutasiWarehouseDTO, NewMutasiWarehouse);
                                                                               foreach (MutasiWarehouseDetail
                                                                                      mutasiWarehouseDetail in
                                                                                      NewMutasiWarehouse.MutasiWarehouseDetails)
                                                                               {
                                                                                   NewMutasiWarehouse.ToWarehouse.
                                                                                       InventoryWarehouses
                                                                                       =
                                                                                       mutasiWarehouseDetail.Inventory.
                                                                                           InventoryWarehouses;
                                                                                   //Mutasi Keluar di Warehouse asal
                                                                                   var mutasiStokWarehouse =
                                                                                       new MutasiStok();
                                                                                   mutasiStokWarehouse.Type =
                                                                                       typeof(MutasiWarehouse).Name;
                                                                                   mutasiStokWarehouse.ReferenceNumber =
                                                                                       NewMutasiWarehouse.NoMutasi;
                                                                                   mutasiStokWarehouse.TglMutasi =
                                                                                      NewMutasiWarehouse.TglMutasi.ToDateTime();
                                                                                   mutasiStokWarehouse.SerialNumber =
                                                                                       mutasiWarehouseDetail.Inventory.
                                                                                           SerialNumber;
                                                                                   mutasiStokWarehouse.KodeWarehouse =
                                                                                       NewMutasiWarehouse.FromWarehouse.
                                                                                           KodeWarehouse;
                                                                                   MutasiStok mutasiLast =
                                                                                       mutasiStokRepository.FindLastMutasi(
                                                                                           mutasiWarehouseDetail.Inventory.SerialNumber,
                                                                                           NewMutasiWarehouse.FromWarehouse.KodeWarehouse
                                                                                           ,mutasiStokWarehouse.TglMutasi
                                                                                           );
                                                                                   mutasiStokWarehouse.QtyKeluar = mutasiWarehouseDetail.Qty;
                                                                                   mutasiStokWarehouse.QtySisa = mutasiLast.QtySisa - mutasiStokWarehouse.QtyKeluar;
                                                                                   mutasiStokWarehouse.SheetKeluar = mutasiWarehouseDetail.Sheet;
                                                                                   mutasiStokWarehouse.SheetSisa = mutasiLast.SheetSisa - mutasiStokWarehouse.SheetKeluar;
                                                                                   mutasiStokWarehouse.PanjangKeluar = mutasiWarehouseDetail.Panjang;
                                                                                   mutasiStokWarehouse.PanjangSisa = mutasiLast.PanjangSisa - mutasiStokWarehouse.PanjangKeluar;
                                                                                   mutasiStokWarehouse.LebarKeluar = mutasiWarehouseDetail.Lebar;
                                                                                   mutasiStokWarehouse.LebarSisa = mutasiLast.LebarSisa - mutasiStokWarehouse.LebarKeluar;
                                                                                   if (mutasiWarehouseDetail.Inventory.Item.IsRounded)
                                                                                       if (mutasiStokWarehouse.QtySisa < batasRounded)
                                                                                           mutasiStokWarehouse.QtySisa = 0;

                                                                                   if (mutasiStokWarehouse.QtySisa < 0)
                                                                                       throw new Exception(
                                                                                           "Stok di gudang " +
                                                                                           MutasiWarehouse.FromWarehouse.
                                                                                               KodeWarehouse +
                                                                                           "  tidak mencukupi!");
                                                                                   mutasiStokRepository.SaveOrUpdate(
                                                                                       mutasiStokWarehouse,mutasiWarehouseDetail.KodePallet);

                                                                                   //Mutasi Masuk di Warehouse Tujuan
                                                                                   var mutasiStokWarehouseDest = new MutasiStok();
                                                                                   mutasiStokWarehouseDest.ReferenceNumber = MutasiWarehouse.NoMutasi;
                                                                                   mutasiStokWarehouseDest.Type = typeof(MutasiWarehouse).Name;
                                                                                   mutasiStokWarehouseDest.TglMutasi = MutasiWarehouse.TglMutasi.ToDateTime();
                                                                                   mutasiStokWarehouseDest.SerialNumber = mutasiWarehouseDetail.Inventory.SerialNumber;
                                                                                   mutasiStokWarehouseDest.KodeWarehouse = MutasiWarehouse.ToWarehouse.KodeWarehouse;
                                                                                   mutasiLast = mutasiStokRepository.FindLastMutasi(
                                                                                           mutasiWarehouseDetail.Inventory.SerialNumber,
                                                                                           NewMutasiWarehouse.ToWarehouse.KodeWarehouse
                                                                                           , mutasiStokWarehouseDest.TglMutasi
                                                                                           );

                                                                                   mutasiStokWarehouseDest.QtyMasuk = mutasiWarehouseDetail.Qty;
                                                                                   mutasiStokWarehouseDest.QtySisa = mutasiLast.QtySisa + mutasiStokWarehouseDest.QtyMasuk;
                                                                                   mutasiStokWarehouseDest.SheetMasuk = mutasiWarehouseDetail.Sheet;
                                                                                   mutasiStokWarehouseDest.SheetSisa = mutasiLast.SheetSisa + mutasiStokWarehouseDest.SheetMasuk;
                                                                                   mutasiStokWarehouseDest.PanjangMasuk = mutasiWarehouseDetail.Panjang;
                                                                                   mutasiStokWarehouseDest.PanjangSisa = mutasiLast.PanjangSisa + mutasiStokWarehouseDest.PanjangMasuk;
                                                                                   mutasiStokWarehouseDest.LebarMasuk = mutasiWarehouseDetail.Lebar;
                                                                                   mutasiStokWarehouseDest.LebarSisa = mutasiLast.LebarSisa + mutasiStokWarehouseDest.LebarMasuk;
                                                                                   if (mutasiWarehouseDetail.Inventory.Item.IsRounded)
                                                                                       if (mutasiStokWarehouseDest.QtySisa < batasRounded)
                                                                                           mutasiStokWarehouseDest.QtySisa = 0;
                                                                                   mutasiStokRepository.SaveOrUpdate(
                                                                                       mutasiStokWarehouseDest, mutasiWarehouseDetail.KodePallet);
                                                                               }
                                                                               MutasiWarehouseRepository.Session.SaveOrUpdateCopy(NewMutasiWarehouse);
                                                                           }else
                                                                           {
                                                                               Mapper.Map(MutasiWarehouseDTO, MutasiWarehouse);
                                                                               //Untuk New entry dari transaksi bukan dari email
                                                                               if (String.IsNullOrEmpty(MutasiWarehouse.NoMutasi))
                                                                                     MutasiWarehouse.NoMutasi = GetLastNoMutasi();

                                                                               //Update Inventory pindahkan Gudangnya
                                                                               foreach (
                                                                                   MutasiWarehouseDetail
                                                                                       mutasiWarehouseDetail in
                                                                                       MutasiWarehouse.
                                                                                           MutasiWarehouseDetails)
                                                                               {
                                                                                   mutasiWarehouseDetail.
                                                                                       MutasiWarehouseDetailId = 0;
                                                                                   MutasiWarehouse.ToWarehouse.
                                                                                       InventoryWarehouses
                                                                                       =
                                                                                       mutasiWarehouseDetail.Inventory.
                                                                                           InventoryWarehouses;
                                                                                   //Mutasi Keluar di Warehouse asal
                                                                                   var mutasiStokWarehouse =
                                                                                       new MutasiStok();
                                                                                   mutasiStokWarehouse.Type =
                                                                                       typeof(MutasiWarehouse).Name;
                                                                                   mutasiStokWarehouse.ReferenceNumber =
                                                                                       MutasiWarehouse.NoMutasi;
                                                                                   mutasiStokWarehouse.TglMutasi =
                                                                                       MutasiWarehouse.TglMutasi.ToDateTime();
                                                                                   mutasiStokWarehouse.SerialNumber =
                                                                                       mutasiWarehouseDetail.Inventory.
                                                                                           SerialNumber;
                                                                                   mutasiStokWarehouse.KodeWarehouse =
                                                                                       MutasiWarehouse.FromWarehouse.
                                                                                           KodeWarehouse;
                                                                                   MutasiStok mutasiLast =
                                                                                       mutasiStokRepository.FindLastMutasi(
                                                                                           mutasiWarehouseDetail.Inventory.SerialNumber,
                                                                                           MutasiWarehouse.FromWarehouse.KodeWarehouse
                                                                                           ,mutasiStokWarehouse.TglMutasi
                                                                                           );
                                                                                   mutasiStokWarehouse.QtyKeluar = mutasiWarehouseDetail.Qty;
                                                                                   mutasiStokWarehouse.QtySisa = mutasiLast.QtySisa - mutasiStokWarehouse.QtyKeluar;
                                                                                   mutasiStokWarehouse.SheetKeluar = mutasiWarehouseDetail.Sheet;
                                                                                   mutasiStokWarehouse.SheetSisa = mutasiLast.SheetSisa - mutasiStokWarehouse.SheetKeluar;
                                                                                   mutasiStokWarehouse.PanjangKeluar = mutasiWarehouseDetail.Panjang;
                                                                                   mutasiStokWarehouse.PanjangSisa = mutasiLast.PanjangSisa - mutasiStokWarehouse.PanjangKeluar;
                                                                                   mutasiStokWarehouse.LebarKeluar = mutasiWarehouseDetail.Lebar;
                                                                                   mutasiStokWarehouse.LebarSisa = mutasiLast.LebarSisa - mutasiStokWarehouse.LebarKeluar;
                                                                                   if (mutasiWarehouseDetail.Inventory.Item.IsRounded)
                                                                                       if (mutasiStokWarehouse.QtySisa < batasRounded)
                                                                                           mutasiStokWarehouse.QtySisa = 0;

                                                                                   if (mutasiStokWarehouse.QtySisa < 0)
                                                                                       throw new Exception(
                                                                                           "Stok di gudang " +
                                                                                           MutasiWarehouse.FromWarehouse.
                                                                                               KodeWarehouse +
                                                                                           "  tidak mencukupi!");
                                                                                   mutasiStokRepository.SaveOrUpdate(
                                                                                       mutasiStokWarehouse, mutasiWarehouseDetail.KodePallet);

                                                                                   //Mutasi Masuk di Warehouse Tujuan
                                                                                   var mutasiStokWarehouseDest =
                                                                                       new MutasiStok();
                                                                                   mutasiStokWarehouseDest.ReferenceNumber =
                                                                                       MutasiWarehouse.NoMutasi;
                                                                                   mutasiStokWarehouseDest.Type =
                                                                                       typeof(MutasiWarehouse).Name;
                                                                                   mutasiStokWarehouseDest.TglMutasi =
                                                                                       MutasiWarehouse.TglMutasi.ToDateTime();
                                                                                   mutasiStokWarehouseDest.SerialNumber =
                                                                                       mutasiWarehouseDetail.Inventory.
                                                                                           SerialNumber;
                                                                                   mutasiStokWarehouseDest.KodeWarehouse =
                                                                                       MutasiWarehouse.ToWarehouse.
                                                                                           KodeWarehouse;
                                                                                   mutasiLast =
                                                                                       mutasiStokRepository.FindLastMutasi(
                                                                                           mutasiWarehouseDetail.Inventory.SerialNumber,
                                                                                           MutasiWarehouse.ToWarehouse.KodeWarehouse
                                                                                           ,mutasiStokWarehouseDest.TglMutasi
                                                                                           );
                                                                                   mutasiStokWarehouseDest.QtyMasuk = mutasiWarehouseDetail.Qty;
                                                                                   mutasiStokWarehouseDest.QtySisa = mutasiLast.QtySisa + mutasiStokWarehouseDest.QtyMasuk;
                                                                                   mutasiStokWarehouseDest.SheetMasuk = mutasiWarehouseDetail.Sheet;
                                                                                   mutasiStokWarehouseDest.SheetSisa = mutasiLast.SheetSisa + mutasiStokWarehouseDest.SheetMasuk;
                                                                                   mutasiStokWarehouseDest.PanjangMasuk = mutasiWarehouseDetail.Panjang;
                                                                                   mutasiStokWarehouseDest.PanjangSisa = mutasiLast.PanjangSisa + mutasiStokWarehouseDest.PanjangMasuk;
                                                                                   mutasiStokWarehouseDest.LebarMasuk = mutasiWarehouseDetail.Lebar;
                                                                                   mutasiStokWarehouseDest.LebarSisa = mutasiLast.LebarSisa + mutasiStokWarehouseDest.LebarMasuk;
                                                                                   if (mutasiWarehouseDetail.Inventory.Item.IsRounded)
                                                                                       if (mutasiStokWarehouseDest.QtySisa < batasRounded)
                                                                                           mutasiStokWarehouseDest.QtySisa =
                                                                                               0;
                                                                                   mutasiStokRepository.SaveOrUpdate(
                                                                                       mutasiStokWarehouseDest, mutasiWarehouseDetail.KodePallet);
                                                                                   //Insert InventoryWarehouse baru dengan gudang Tujuan
                                                                               }

                                                                               MutasiWarehouseRepository.SaveOrUpdate(MutasiWarehouse);
                                                                           }
                                                                          
                                                                       });


                res = true;
            }
            catch (Exception ex)
            {
                res = false;
                throw ex;
            }

            return res;
        }


        public bool Delete(MutasiWarehouseDTO MutasiWarehouseDto)
        {
            bool res;
            try
            {
                MutasiWarehouse MutasiWarehouse =
                    MutasiWarehouseRepository.GetDataOne(x => x.NoMutasi == MutasiWarehouseDto.NoMutasi);
                //MutasiWarehouseRepository.Delete(MutasiWarehouse);
                MutasiWarehouse.Status = Convert.ToInt16(Status.Void);

                MutasiWarehouseRepository.ExecuteTransactionNative(() => mutasiStokRepository.DeleteMutasiStok(
                    MutasiWarehouse.NoMutasi));

                res = true;
            }
            catch (Exception)
            {
                res = false;
            }

            return res;
        }


        public List<MutasiWarehouseDTO> GetListByCriteria(Dictionary<String, Object> criteria, string expression,
                                                          int page, out long recordCount)
        {
            var MutasiWarehouses = new List<MutasiWarehouse>();
            var Results = new List<MutasiWarehouseDTO>();
            MutasiWarehouses = MutasiWarehouseRepository.GetDataPaged(criteria, expression, page, 30).ToList();
            recordCount = MutasiWarehouseRepository.RecordCount;
            MutasiWarehouses.ForEach(x =>
                                         {
                                             var MutasiWarehouseDto = new MutasiWarehouseDTO();
                                             MutasiWarehouseDto.InjectFrom<CloneInjection>(x);
                                             Results.Add(MutasiWarehouseDto);
                                         }
                );

            return Results;
        }


        public List<MutasiWarehouseDTO> GetAllMutasiWarehouse()
        {
            List<MutasiWarehouse> MutasiWarehouses = MutasiWarehouseRepository.FetchAll().ToList();
            var Results = new List<MutasiWarehouseDTO>();
            MutasiWarehouses.ForEach(x =>
                                         {
                                             var MutasiWarehouseDto = new MutasiWarehouseDTO();
                                             MutasiWarehouseDto.InjectFrom<CloneInjection>(x);
                                             Results.Add(MutasiWarehouseDto);
                                         }
                );

            return Results;
        }


        public MutasiWarehouseDTO GetMutasiWarehouse(String kodeMutasiWarehouse)
        {
            MutasiWarehouse MutasiWarehouse =
                MutasiWarehouseRepository.GetDataOne(x => x.NoMutasi == kodeMutasiWarehouse);
            var MutasiWarehouseDto = new MutasiWarehouseDTO();
            MutasiWarehouseDto.InjectFrom<CloneInjection>(MutasiWarehouse);
            return MutasiWarehouseDto;
        }

        public List<MutasiWarehouseDTO> GetMutasiWarehouseList(string kodeMutasiWarehouse)
        {
            List<MutasiWarehouse> MutasiWarehouses =
                MutasiWarehouseRepository.GetDataList(x => x.NoMutasi.Contains(kodeMutasiWarehouse)).ToList();
            var Results = new List<MutasiWarehouseDTO>();
            MutasiWarehouses.ForEach(x =>
                                         {
                                             var MutasiWarehouseDto = new MutasiWarehouseDTO();
                                             MutasiWarehouseDto.InjectFrom<CloneInjection>(x);
                                             Results.Add(MutasiWarehouseDto);
                                         }
                );

            return Results;
        }

        public string GetLastNoMutasi()
        {
            var appParamServices = new AppParamServices();
            AppParamDTO param = appParamServices.GetAppParamList("KodeTG").FirstOrDefault();
            string res = MutasiWarehouseRepository.GetMaxNumber(param.AppParamValue);
           
            if (string.IsNullOrEmpty(res))
                res = param.AppParamValue;

            string formatSO = "0000";
            string lastNo = string.Empty;
            string kodeSO;
            string last = string.Empty;
            if (res.Length <= 4)
            {
                lastNo = formatSO;
                kodeSO = res;
            }
            else
            {
                lastNo = res.Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[2];
                kodeSO = res.Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0];
            }
            string soNum = formatSO.Substring(0, formatSO.Length - (int.Parse(lastNo) + 1).ToString().Length) +
                           (int.Parse(lastNo) + 1);

            return kodeSO + "/" + DateTime.Now.Year + "/" + soNum;
        }


        public bool DeleteDetail(MutasiWarehouseDetailDTO mutasiWarehouseDetailDto)
        {
            bool res;
            try
            {
                var MutasiWareHouseDetail =
                    MutasiWarehouseRepository.Session.Get<MutasiWarehouseDetail>(
                        mutasiWarehouseDetailDto.MutasiWarehouseDetailId);
                MutasiWarehouseRepository.DeleteDetail(MutasiWareHouseDetail,
                                                       mutasiWarehouseDetailDto.MutasiWarehouseDetailId);
                res = true;
            }
            catch (Exception)
            {
                res = false;
            }

            return res;
        }

        public bool SendEmail(MutasiWarehouseDTO obj, String DestinationFolder)
        {
            var mailServices = new MailServices();
            MutasiWarehouse Obj = MutasiWarehouseRepository.GetDataOne(x => x.NoMutasi == obj.NoMutasi);
            obj = Mapper.Map(Obj, obj);
            return mailServices.SendEmail(obj,DestinationFolder);
        }

        public void UpdateStatus(MutasiWarehouseDTO mutasiWarehouseDto, Status status)
        {
            MutasiWarehouseRepository.UpdateStatus(mutasiWarehouseDto.NoMutasi, (int)status);
        }

        #endregion
    }
}